#ifndef _MODESTO_SERVER_H_
#define _MODESTO_SERVER_H_

#include <string>
#include "../definitions.h"
#include "connection.h"
#include "command.h"
#include "channel.h"
#include "user.h"

struct ServerInfo
{
	// The address which will be connect to.
	std::string address;

	// The port number of the server.
	std::string port;

	// The host name of the server.
	std::string host;

	// The nick name which will be assigned to this connection.
	std::string nick;

	// The password to authenticate on the servers nick services.
	std::string nickServPass;

	// List of the channels to join on connect.
	std::vector<std::string> channels;

	// Instantiate a new instance of server information.
	ServerInfo()
	{
		this->address	= "";
		this->host	= DEFAULT_HOST;
		this->port	= DEFAULT_PORT;
		this->nick	= DEFAULT_NICK;
		this->nickServPass.erase();
		this->channels = std::vector<std::string>();
	}

	// Instantiate a new instance of server information.
	ServerInfo(std::string address) : address(address)
	{
		this->host = DEFAULT_HOST;
		this->port = DEFAULT_PORT;
		this->nick = DEFAULT_NICK;
		this->nickServPass.erase();
		this->channels = std::vector<std::string>();
	}

	// Instantiate a new instance of server information.
	ServerInfo(std::string address, std::string port) : address(address), port(port)
	{
		this->nick = DEFAULT_NICK;
		this->host = DEFAULT_HOST;
		this->nickServPass.erase();
		this->channels = std::vector<std::string>();
	}

	// Instantiate a new instance of server information.
	ServerInfo(std::string address, std::string port, std::string nick) : address(address), port(port), nick(nick)
	{
		this->host = DEFAULT_HOST;
		this->nickServPass.erase();
		this->channels = std::vector<std::string>();
	}

	// Instantiate a new instance of server information.
	ServerInfo(std::string address, std::string port, std::string nick, std::string nickServPass) : address(address), port(port), nick(nick), nickServPass(nickServPass)
	{
		this->host = DEFAULT_HOST;
		this->channels = std::vector<std::string>();
	}

	// Instantiate a new instance of server information.
	ServerInfo(std::string address, std::string port, std::string nick, std::string nickServPass, std::vector<std::string> channels) : address(address), port(port), nick(nick), nickServPass(nickServPass), channels(channels)
	{
		this->host = DEFAULT_HOST;
	}
};

class Server
{
public:
	// Create a new connection to an IRC server.
	Server(ServerInfo info);

	SOCKET getConnection();

	// Connect to the server.
	bool connect();

	// Disconnect from the server.
	void disconnect();

	// Check if the client is connected to the server.
	bool isConnected();

	// Send a message to the server.
	void send(std::string message);

	// Receive a message from the server.
	std::string receive(int max_length);

	// Returns the server information.
	ServerInfo getServerInfo();

	// Add a channel to the list.
	void addChannel(Channel *channel);

	// Add a channel to the list.
	Channel *addChannel(std::string name);

	// Remove the channel from the list.
	void removeChannel(std::string name);

	// Returns the list of channels.
	ChannelList getChannelList();

	// Check to see if the bot is already in the channel.
	bool hasChannel(std::string name);

	// Return the channel.
	Channel *getChannel(std::string name);
	
	void addUser(User *user);
	User *addUser(std::string name);
	bool hasUser(std::string name);
	User *getUser(std::string name);
	void removeUser(std::string name);
	UserList getUserList();

	// Add the channel to the list of current channels.
	void join(std::string name);
	
	// Remove the channel from the list of current channels.
	void part(std::string name);

protected:
	ServerInfo info;
	Connection *conn;

	UserList users;
	ChannelList channels;
};

typedef std::map<int, Server *> ServerList;
typedef std::pair<int, Server *> ServerListItem;
typedef std::map<int, Server *>::iterator ServerListIter;

#endif